package com.ruoyi.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.BsShouye;
import com.ruoyi.system.domain.vo.BsShouyeVo;
import com.ruoyi.system.mapper.BsShouyeMapper;
import com.ruoyi.system.service.BsShouyeService;
import com.ruoyi.system.service.ISysDictTypeService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description TODO
 * @ClassName BsShouyeServiceImpl
 * @Author kenn
 * @Version 1.0.0
 * @Date 2023年11月23日 11:36:00
 */
@Service
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class BsShouyeServiceImpl extends ServiceImpl<BsShouyeMapper, BsShouye> implements BsShouyeService {

    private final ISysDictTypeService dictTypeService;

    @Override
    public TableDataInfo<BsShouye> pageList(PageDomain pageDomain, BsShouyeVo shouyeVo) {
        LambdaQueryWrapper<BsShouye> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotEmpty(shouyeVo.getImgType()), BsShouye::getImgType, shouyeVo.getImgType());
        queryWrapper.eq(StringUtils.isNotEmpty(shouyeVo.getImgStatus()), BsShouye::getImgStatus, shouyeVo.getImgStatus());
        queryWrapper.between(StringUtils.isNotEmpty(shouyeVo.getStartTime()) && StringUtils.isNotEmpty(shouyeVo.getEndTime()), BsShouye::getCreateTime, shouyeVo.getStartTime() + " 00:00:00", shouyeVo.getEndTime() + " 23:59:59");
        queryWrapper.orderByAsc(BsShouye::getSort);
        PageHelper.startPage(pageDomain.getPageNum(), pageDomain.getPageSize());
        List<BsShouye> shouyeList = list(queryWrapper);
        buildRelationInfo(shouyeList);
        PageInfo<BsShouye> pageInfo = new PageInfo<>(shouyeList);
        return new TableDataInfo<>(pageInfo.getList(), pageInfo.getTotal());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveEntity(BsShouye shouye) {
        boolean flag;
        // 非分布式系统 synchronized关键字即可
        synchronized (BsShouyeServiceImpl.class) {
            Integer sort = baseMapper.selectMaxSort();
            Assert.notNull(sort, "获取排序值失败,请刷新后重试");
            shouye.setSort(sort);
            flag = save(shouye);
        }
        return flag;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateEntity(BsShouye shouye) {
        return updateById(shouye);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(Long id) {
        Assert.notNull(id, "主键id不能为空");
        return removeById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean move(Long id, String type) {
        boolean moveSelf;
        boolean moveOther;
        // 非分布式系统 synchronized关键字即可
        synchronized (BsShouyeServiceImpl.class) {
            BsShouye toMove = getById(id);
            Assert.notNull(toMove, "该任务不存在或已被删除");

            Integer sort = null;
            StrBuilder errorMsg = new StrBuilder("");
            LambdaQueryWrapper<BsShouye> queryWrapper = new LambdaQueryWrapper<>();
            List<BsShouye> changeList = null;
            if ("top".equalsIgnoreCase(type)) {
                queryWrapper.lt(BsShouye::getSort, toMove.getSort());
                changeList = list(queryWrapper);
                if (CollUtil.isNotEmpty(changeList)) {
                    sort = changeList.get(0).getSort();
                    changeList.parallelStream().forEach(i->i.setSort(i.getSort() + 1));
                }
                errorMsg.append("已经是首节点");
            } else if ("up".equalsIgnoreCase(type)) {
                queryWrapper.lt(BsShouye::getSort, toMove.getSort()).orderByDesc(BsShouye::getSort).last("limit 1");
                BsShouye temp = getOne(queryWrapper);
                if (ObjectUtil.isNotNull(temp)) {
                    sort = temp.getSort();
                    temp.setSort(toMove.getSort());
                    changeList = Collections.singletonList(temp);
                }
                errorMsg.append("已经是首节点");
            } else if ("down".equalsIgnoreCase(type)) {
                queryWrapper.gt(BsShouye::getSort, toMove.getSort()).orderByAsc(BsShouye::getSort).last("limit 1");
                BsShouye temp = getOne(queryWrapper);
                if (ObjectUtil.isNotNull(temp)) {
                    sort = temp.getSort();
                    temp.setSort(toMove.getSort());
                    changeList = Collections.singletonList(temp);
                }
                errorMsg.append("已经是尾节点");
            } else if ("bottom".equalsIgnoreCase(type)) {
                queryWrapper.gt(BsShouye::getSort, toMove.getSort());
                changeList = list(queryWrapper);
                if (CollUtil.isNotEmpty(changeList)) {
                    sort = changeList.get(changeList.size() - 1).getSort();
                    changeList.parallelStream().forEach(i->i.setSort(i.getSort() - 1));
                }
                errorMsg.append("已经是尾节点");
            }

            Assert.notEmpty(changeList, errorMsg.toString());
            toMove.setSort(sort);
            moveSelf = updateById(toMove);
            moveOther = updateBatchById(changeList);
        }
        return moveSelf && moveOther;
    }

    public void buildRelationInfo(List<BsShouye> shouyeList) {
        if (CollUtil.isNotEmpty(shouyeList)) {
            List<SysDictData> typeDictList = dictTypeService.selectDictDataByType(Constants.SHOUYE_IMG_TYPE);
            Map<String, SysDictData> typeMap = null;
            if (CollUtil.isNotEmpty(typeDictList)) {
                typeMap = typeDictList.stream().collect(Collectors.toMap(SysDictData::getDictValue, Function.identity()));
            }
            for (BsShouye shouye : shouyeList) {
                if (CollUtil.isNotEmpty(typeMap)) {
                    shouye.setImgTypeName(ObjectUtil.isNotNull(typeMap.get(shouye.getImgType())) ? typeMap.get(shouye.getImgType()).getDictLabel() : "");
                }
            }
        }
    }

}
